--[[


THIS FILE CONTAINS ALL THE INTERNAL FUNCTIONS THAT ARE NOT TO BE CALLED DIRECTLY




]]


gdatabase.lib = {}

--this function starts a keep alive timer that will refresh at the speed set in gdatabase.config
function gdatabase.lib.keepalive(intDatabaseIndex)
--ok so we basically call a keep alive timer and thats it
	local tblSettings = gdatabase.connections[intDatabaseIndex].settings
	ptimer.Create("gdatabase_keepalive_index_" .. intDatabaseIndex,tblSettings["keepaliverefresh"], 0, gdatabase.lib.keepalivetimer, intDatabaseIndex)
	
	if gdatabase.config.debug then
		Msg("Database Keep Alive Started!\n")
	end
	

end

--this function is the actual keep alive timer. It calls threaded queries that callback to gdatabase.lib.keepalivecallback
function gdatabase.lib.keepalivetimer(intDatabaseIndex)
	
	gdatabase.threadedquery("SELECT 1 + 1", intDatabaseIndex, gdatabase.lib.keepalivetimercallback, intDatabaseIndex)


end

--this function is 
function gdatabase.lib.keepalivetimercallback(query, intDatabaseIndex)
	--run the hook
	gdatabase.lib.runhooks("keepalive", intDatabaseIndex)
	
	if(query == 0) then
		
		Msg("GDATABASE: Database:" .. gdatabase.connections[intDatabaseIndex].databasename .. " has timed out\n")
		gdatabase.lib.killconnection(intDatabaseIndex)
		if(gdatabase.lib.createconnection(intDatabaseIndex) ~= 1) then
			--the connection is still unsuccessful so lets do a reconnection timer
			--Run the hook table	
			local tblSettings = gdatabase.connections[intDatabaseIndex].settings
			ptimer.Create("gdatabaseReconnect" .. tostring(intDatabaseindex), tblSettings["reconnectrate"], 0, gdatabase.lib.reconnecttimer, intDatabaseIndex)
			ptimer.Remove("gdatabase_keepalive_index_" .. intDatabaseIndex)
		end
	
	
	end
	
end

function gdatabase.lib.reconnecttimer(intDatabaseIndex)
	local tblSettings = gdatabase.connections[intDatabaseIndex].settings
	if(gdatabase.lib.createconnection(intDatabaseIndex) == 1) then
		Msg("GDATABASE: RECONNECTION SUCCESSFUL!!\n")
		ptimer.Remove("gdatabaseReconnect" .. tostring(intDatabaseindex))
		gdatabase.lib.keepalive(intDatabaseIndex)
		
		--Run the Hook
		gdatabase.lib.runhooks("reconnect", intDatabaseIndex)
		
		return
	end
end


--internal function that kills the database connection without killing the index, useful for manual reconnects to the same index
function gdatabase.lib.killconnection(intDatabaseIndex)
	--Run the Hook
	gdatabase.lib.runhooks("disconnect", intDatabaseIndex)
	
	local succ, error = mysql.disconnect(gdatabase.connections[intDatabaseIndex].database)
	
	if (not succ) then Msg("GDATABASE:" .. error .. "\n") end 
	--Kill all the thread timers associated with this database to prevent problems
	ptimer.Remove("gdatabasethreadqueue" .. tostring(intDatabaseindex))
	ptimer.StopGroup("gdatabase_connection" .. intDatabaseIndex)
	for i,v in pairs(gdatabase.connections[intDatabaseIndex].threads.active) do
		gdatabase.lib.removethread(v)
	end
	gdatabase.connections[intDatabaseIndex].threads = nil
	gdatabase.connections[intDatabaseIndex].status = false


end

--removes the thread, tblThread is the table with the thread contents in it.
function gdatabase.lib.removethread(tblThread)
	mysql.query_cleanup(tblThread["threadid"]) --clean up the thread in case it was started.
end

function gdatabase.lib.createconnection(intDatabaseIndex)
	local tblConnection = gdatabase.connections[intDatabaseIndex]
	--remake the connection, YAY for long ass table syntax
	tblConnection.database, err = mysql.connect(tblConnection.databasehost, tblConnection.databaseuser, tblConnection.databasepassword, tblConnection.databasename)
	--checks for a connection
	if (tblConnection.database == 0) then
		return 0
	end
	
	tblConnection.threads = {}
	tblConnection.threads.queue = {}
	tblConnection.threads.active = {}
	tblConnection.threads.queuetime = 0
	tblConnection.threads.processing = 0
	tblConnection.status = true
	ptimer.StartGroup("gdatabase_connection" .. intDatabaseIndex)
	
	--Run the Hook
	gdatabase.lib.runhooks("connect", intDatabaseIndex)
	
	return 1

end

function gdatabase.lib.runhooks(strHookName, intDatabaseIndex)
	if !gdatabase.CheckForConnection(intDatabaseIndex) then return false end
	if gdatabase.connections[intDatabaseIndex].hooks[strHookName] == nil then return false end
	
	for k,v in pairs(gdatabase.connections[intDatabaseIndex].hooks[strHookName]) do
		local run, error = pcall(v.Func, unpack(v.Args))
		if !run then 
			Msg("GDATABASE: Hook Error:" .. error .. "\n")
			Msg("GDATABASE: Removing Hook:" .. strHookName .. " Name:" .. k .. "\n")
			v = nil
		end
	end


end

function gdatabase.lib.loadsettings(tblCustomSettings)
	local tblSettings = table.Copy(gdatabase.config)
	
	if tblCustomSettings != nil then
		for k,v in pairs(tblCustomSettings) do
			tblSettings[k] = v	
		end
	end
	return tblSettings
end

function gdatabase.lib.shutdown()
	for k, v in pairs(gdatabase.connections) do
		gdatabase.lib.runhooks("shutdown", k)
		gdatabase.KillConnection(k)
	end
	Msg("GDATABASE: All connections disabled\n")
end
hook.Add( "ShutDown", "gdatabaseshutdown", gdatabase.lib.shutdown)

function gdatabase.lib.playercanrun(ply)
	if ply and !ply:IsValid() then --Console
		return true
	elseif( ply and ply:IsAdmin()) then
		return true
	else
		return false
	end
end



